package cn.siriusbot.rpc.server;

import cn.siriusbot.rpc.PrintLog;
import cn.siriusbot.rpc.RpcContext;
import cn.siriusbot.rpc.SiriusBotRpcServer;
import cn.siriusbot.rpc.SiriusLogger;
import cn.siriusbot.rpc.context.AbstractRpcContext;
import cn.siriusbot.rpc.entity.RpcBody;
import cn.siriusbot.rpc.entity.RpcNativeBody;
import cn.siriusbot.siriuspro.error.MsgException;
import lombok.SneakyThrows;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

public abstract class BasicsSiriusBotRpcServer extends AbstractRpcContext implements SiriusBotRpcServer, RpcContext {

    protected Map<String, Object> rpcMap = new ConcurrentHashMap<>();

    protected SiriusLogger log = new PrintLog();

    public BasicsSiriusBotRpcServer(SiriusLogger log) {
        this.log = log;
    }

    public BasicsSiriusBotRpcServer() {
    }

    /**
     * 注册Rpc服务
     *
     * @param clazz  rpc类
     * @param source 预注册的对象
     */
    @Override
    public <T> void register(Class<T> clazz, T source) {
        rpcMap.put(getName(clazz.getName()), source);
    }

    /**
     * 获取一个处理结果
     *
     * @param body 请求详细
     * @return 返回结果
     */
    @SneakyThrows
    @Override
    public Object getResult(RpcBody body) {
        final RpcNativeBody rpcNativeBody = this.parsecRpcBody(body);
        return rpcNativeBody.getMethod().invoke(rpcNativeBody.getApi(), rpcNativeBody.getParam());
    }


    private String getName(String name) {
        try {
            return name.substring(name.lastIndexOf(".") + 1);
        } catch (Throwable e) {
            return name;
        }
    }

    /**
     * 寻找api的类
     *
     * @param apiName api名称
     * @return api对象
     */
    @Override
    protected Object findApiClass(String apiName) {
        final Object o = rpcMap.get(getName(apiName));
        if (o == null) throw new MsgException(500, String.format("找不到Api为[%s]的RPC对象!", apiName));
        return o;
    }

    /**
     * 寻找api执行的方法
     *
     * @param apiObj api对象
     * @param method api方法名称
     * @return 方法对象
     */
    @Override
    protected Method findApiMethod(Object apiObj, String method) {
        final Class<?> clazz = apiObj.getClass();
        final Method[] methods = clazz.getMethods();
        final Optional<Method> first = Arrays.stream(methods).filter(s -> s.getName().equals(method)).findFirst();
        if (!first.isPresent()) throw new MsgException(500, "找不到RPC方法!");
        return first.get();
    }
}
